namespace ExpressIS.NetduinoDeviceLibrary {
  using System;
  using Microsoft.SPOT.Hardware;

  public abstract class I2CDeviceHelper : IDisposable {
    protected bool _disposed = false;
    protected readonly I2CDevice _sharedI2C;
    protected readonly I2CDevice.Configuration _configuration;
    protected readonly int _transactionTimeoutMs;

    public I2CDeviceHelper(I2CDevice sharedI2C, ushort hardwareAddress, int clockRateKHz, int transacitonTimeoutMs) {
      this._sharedI2C = sharedI2C;
      this._transactionTimeoutMs = transacitonTimeoutMs;
      this._configuration = new I2CDevice.Configuration(hardwareAddress, clockRateKHz);
    }

    protected delegate void Action();
    protected void SwapConfiguration(Action i2cAction) {
      // There is no shared lock on the I2C instance, so just use the class instance itself (not recomended, but its all we have)
      lock (this._sharedI2C) {
        // Get the current configuration for the I2C and save it locally so we can put it back.
        var originalConfiguration = this._sharedI2C.Config;
        try {
          // Swap in our new configuration
          this._sharedI2C.Config = this._configuration;

          // Run the action for this configuration;
          i2cAction();
        }
        finally {
          // Put the original configurationback in place.
          this._sharedI2C.Config = originalConfiguration;
        }
      }
    }

    protected static int BcdToDec(int value) {
      return ((value / 16 * 10) + (value % 16));
    }

    protected static byte DecToBcd(int value) {
      return (byte)((value / 10 * 16) + (value % 10));
    }

    public void Dispose() {
      this.Dispose(true);
    }

    protected abstract void Dispose(bool disposing);
  }
}
